/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.marist.cs.os.g3.processors;

import edu.marist.cs.os.g3.mos.Buffer;
import edu.marist.cs.os.g3.mos.Memory;
import edu.marist.cs.os.g3.vm.Drum;

/**
 *
 * @author Intern
 */
public class Channel3 {

    public static final int TIME_REQUIRED = 2;
    public static final int IOI_VALUE = 4;
    int timer = 0;
    Buffer buffer = new Buffer();
    boolean busy = false;
    CPU cpu;
  
    public static enum Task {

        INPUT_SPOOL, OUTPUT_SPOOL, LOAD, GD, PD
    };
    Task task;
    Drum drum;
    Memory memory;
    int track = -1;
    int frame = -1;

    public Channel3(CPU cpu, Drum drum, Memory memory) {
        this.cpu = cpu;
        this.drum = drum;
        this.memory = memory;
    }

    public boolean startTask(Task task, Buffer buffer, int track, int frame) {
        if (busy) {
            return false;
        }
        this.task = task;
        switch (task) {
            case INPUT_SPOOL:
                
            case OUTPUT_SPOOL:
                this.buffer = buffer;
                this.track = track;
                break;
            case LOAD:
                this.track = track;
                this.frame = frame;
                break;
            case GD:
                this.track = track;
                this.frame = frame;
                break;

            case PD:
                this.track = track;
                this.frame = frame;
                break;
        }
        timer = 0;
        busy = true;
        return true;
    }

    public void cycleComplete() {
        timer++;
        if (busy && timer == Channel3.TIME_REQUIRED) {
            //Complete simulation
            switch (task) {
                case INPUT_SPOOL:
                    drum.fillTrack(buffer.toString(), track);

                    buffer.setEmpty();
                    break;
                case OUTPUT_SPOOL:
                    buffer.setData(drum.getTrack(track).toString());
                    drum.freeBlock(track);
                    break;
                //Does not deal with buffers
                case LOAD:
                    memory.getBlock(frame).setEmpty(true);
                    memory.fillBlock(drum.getTrack(track).toString(), frame);
                    memory.getBlock(frame).setEmpty(false);
                    //drum.freeBlock(track);

                    break;
                case GD:
                    memory.getBlock(frame).setEmpty(true);
                    memory.fillBlock(drum.getTrack(track).toString(), frame);
                    memory.getBlock(frame).setEmpty(false);
                    //drum.freeBlock(track);
                    break;
                //Also does not deal with buffers
                case PD:
                    drum.fillTrack(memory.getBlock(frame).toString(), track);
               
                    break;
            }
            cpu.IOI += Channel3.IOI_VALUE;
            busy = false;
        }

    }

    public boolean isBusy() {
        return busy;
    }

    public Channel3.Task getTask() {
        return task;
    }

    public Buffer getBuffer() {
        return buffer;
    }

    public int getTrack() {
        return track;
    }
}
